package com.graduation.check.service;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.graduation.check.dto.*;
import com.graduation.check.entity.*;
import com.graduation.check.mapper.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class TitleCheckService {

    @Autowired
    private TitleCheckTaskMapper titleCheckTaskMapper;

    @Autowired
    private TitleDuplicateResultMapper duplicateResultMapper;

    @Autowired
    private CheckTaskMapper checkTaskMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private PaperExtractionTaskMapper paperExtractionTaskMapper;

    @Autowired
    private ObjectMapper objectMapper;

    @Transactional
    public TitleCheckResponse submitTitleCheck(TitleCheckRequest request, Long studentId) {
        try {
            log.info("开始题目查重 - 学生ID: {}, 题目: {}", studentId, request.getTitle());

            // 创建查重任务
            TitleCheckTask task = new TitleCheckTask();
            task.setStudentId(studentId);
            task.setTitle(request.getTitle());
            task.setDescription(request.getDescription());
            task.setCheckScope(request.getCheckScope());
            task.setYearRange(request.getYearRange());
            task.setStatus("PROCESSING");
            task.setCheckTime(LocalDateTime.now());

            // 设置默认值，避免空指针
            task.setMaxSimilarity(0.0);
            task.setAvgSimilarity(0.0);
            task.setDuplicateCount(0);
            task.setRiskLevel("low");

            titleCheckTaskMapper.insert(task);
            log.info("创建查重任务成功，任务ID: {}", task.getId());

            // 执行查重分析
            TitleCheckResponse response = performTitleAnalysis(task, request);
            log.info("查重分析完成，相似题目数量: {}", response.getDuplicateResults().size());

            // 更新任务状态和结果
            task.setMaxSimilarity(response.getMaxSimilarity());
            task.setAvgSimilarity(response.getAvgSimilarity());
            task.setDuplicateCount(response.getDuplicateCount());
            task.setRiskLevel(response.getRiskLevel());
            task.setStatus("COMPLETED");

            // 保存相似结果到数据库
            if (response.getDuplicateResults() != null && !response.getDuplicateResults().isEmpty()) {
                saveDuplicateResults(task.getId(), response.getDuplicateResults());
            }

            // 保存建议到数据库
            if (response.getSuggestions() != null) {
                try {
                    task.setSuggestions(objectMapper.writeValueAsString(response.getSuggestions()));
                } catch (Exception e) {
                    log.warn("序列化建议失败", e);
                }
            }

            titleCheckTaskMapper.update(task);
            log.info("查重任务更新完成");

            return response;

        } catch (Exception e) {
            log.error("题目查重失败", e);
            throw new RuntimeException("题目查重失败: " + e.getMessage());
        }
    }

    private TitleCheckResponse performTitleAnalysis(TitleCheckTask task, TitleCheckRequest request) {
        List<CheckTask> papersToCompare = getPapersToCompare(task.getStudentId(),
                request.getCheckScope(),
                request.getYearRange());

        log.info("获取到 {} 篇论文用于比较", papersToCompare.size());

        String inputTitle = request.getTitle().toLowerCase().trim();
        List<TitleCheckResponse.DuplicateResult> duplicateResults = new ArrayList<>();

        for (CheckTask paper : papersToCompare) {
            if (paper.getPaperTitle() == null || paper.getPaperTitle().trim().isEmpty()) continue;

            String compareTitle = paper.getPaperTitle().toLowerCase().trim();
            double similarity = calculateTitleSimilarity(inputTitle, compareTitle);

            // 降低相似度阈值，显示更多结果
            if (similarity > 0.05) {
                TitleCheckResponse.DuplicateResult result = new TitleCheckResponse.DuplicateResult();
                result.setTitle(paper.getPaperTitle());
                result.setSimilarity(Math.round(similarity * 10000) / 100.0); // 保留两位小数
                result.setPaperId(paper.getId());

                // 获取作者信息
                User author = userMapper.findById(paper.getStudentId());
                if (author != null) {
                    result.setAuthor(author.getName());
                    result.setClassName(author.getClassName());
                } else {
                    result.setAuthor("未知作者");
                    result.setClassName("未知班级");
                }

                // 设置年份
                if (paper.getUploadTime() != null) {
                    result.setYear(paper.getUploadTime().getYear());
                } else {
                    result.setYear(LocalDateTime.now().getYear());
                }

                duplicateResults.add(result);
                log.debug("发现相似题目: {} (相似度: {}%)", paper.getPaperTitle(), result.getSimilarity());
            }
        }

        // 按相似度降序排序
        duplicateResults.sort((a, b) -> Double.compare(b.getSimilarity(), a.getSimilarity()));

        TitleCheckResponse response = new TitleCheckResponse();
        response.setId(task.getId());
        response.setTitle(request.getTitle());
        response.setCheckScope(request.getCheckScope());
        response.setYearRange(request.getYearRange());
        response.setCheckTime(task.getCheckTime());
        response.setDuplicateResults(duplicateResults);

        if (!duplicateResults.isEmpty()) {
            double maxSimilarity = duplicateResults.get(0).getSimilarity();
            double avgSimilarity = duplicateResults.stream()
                    .mapToDouble(TitleCheckResponse.DuplicateResult::getSimilarity)
                    .average()
                    .orElse(0);
            avgSimilarity = Math.round(avgSimilarity * 100) / 100.0; // 保留两位小数

            response.setMaxSimilarity(maxSimilarity);
            response.setAvgSimilarity(avgSimilarity);
            response.setDuplicateCount(duplicateResults.size());
            response.setRiskLevel(calculateRiskLevel(maxSimilarity));

            log.info("查重结果 - 最高相似度: {}%, 平均相似度: {}%, 相似数量: {}",
                    maxSimilarity, avgSimilarity, duplicateResults.size());
        } else {
            response.setMaxSimilarity(0.0);
            response.setAvgSimilarity(0.0);
            response.setDuplicateCount(0);
            response.setRiskLevel("low");
            log.info("查重结果 - 未发现相似题目");
        }

        response.setSuggestions(generateSuggestions(response));
        return response;
    }

    private List<CheckTask> getPapersToCompare(Long studentId, String checkScope, Integer yearRange) {
        LocalDateTime startDate = null;

        // 修正：当前范围查重时，yearRange可能为0
        if (yearRange != null && yearRange > 0) {
            startDate = LocalDateTime.now().minusYears(yearRange);
            log.info("设置时间范围: {}年前", yearRange);
        }

        List<CheckTask> papers;

        switch (checkScope) {
            case "current":
                // 修正：当前年份查重逻辑
                LocalDateTime currentYearStart = LocalDateTime.now().withMonth(1).withDayOfMonth(1).withHour(0).withMinute(0).withSecond(0);
                papers = checkTaskMapper.findOtherStudentsRecentPapers(studentId, currentYearStart);
                log.info("当前范围查重: 获取{}篇论文", papers.size());
                break;

            case "history":
                if (startDate != null) {
                    papers = checkTaskMapper.findOtherStudentsRecentPapers(studentId, startDate);
                } else {
                    // 如果没有指定年份范围，查询所有历史数据
                    papers = checkTaskMapper.findOtherStudentsPapers(studentId);
                }
                log.info("历史范围查重: 获取{}篇论文", papers.size());
                break;

            case "current_and_history":
            default:
                if (startDate != null) {
                    papers = checkTaskMapper.findOtherStudentsRecentPapers(studentId, startDate);
                } else {
                    papers = checkTaskMapper.findOtherStudentsPapers(studentId);
                }
                log.info("全面范围查重: 获取{}篇论文", papers.size());
                break;
        }

        return papers;
    }

    private double calculateTitleSimilarity(String title1, String title2) {
        if (title1.equalsIgnoreCase(title2)) {
            return 1.0;
        }

        // 使用Jaccard相似度计算词语重叠
        Set<String> words1 = new HashSet<>(Arrays.asList(title1.split("\\s+")));
        Set<String> words2 = new HashSet<>(Arrays.asList(title2.split("\\s+")));

        Set<String> intersection = new HashSet<>(words1);
        intersection.retainAll(words2);
        Set<String> union = new HashSet<>(words1);
        union.addAll(words2);

        double jaccardSimilarity = union.isEmpty() ? 0 : (double) intersection.size() / union.size();

        // 使用编辑距离计算字符串相似度
        double editDistanceSimilarity = 1 - (calculateEditDistance(title1, title2) /
                (double) Math.max(title1.length(), title2.length()));

        // 综合两种相似度算法
        return (jaccardSimilarity * 0.6 + editDistanceSimilarity * 0.4);
    }

    private int calculateEditDistance(String s1, String s2) {
        int[][] dp = new int[s1.length() + 1][s2.length() + 1];

        for (int i = 0; i <= s1.length(); i++) {
            for (int j = 0; j <= s2.length(); j++) {
                if (i == 0) {
                    dp[i][j] = j;
                } else if (j == 0) {
                    dp[i][j] = i;
                } else {
                    dp[i][j] = Math.min(Math.min(
                                    dp[i - 1][j] + 1,
                                    dp[i][j - 1] + 1),
                            dp[i - 1][j - 1] + (s1.charAt(i - 1) == s2.charAt(j - 1) ? 0 : 1)
                    );
                }
            }
        }

        return dp[s1.length()][s2.length()];
    }

    private String calculateRiskLevel(double maxSimilarity) {
        if (maxSimilarity < 15) {
            return "low";
        } else if (maxSimilarity < 30) {
            return "medium";
        } else {
            return "high";
        }
    }

    private List<String> generateSuggestions(TitleCheckResponse response) {
        List<String> suggestions = new ArrayList<>();

        if (response.getMaxSimilarity() < 15) {
            suggestions.add("题目重复率较低，可以使用");
            suggestions.add("建议再次确认题目的独特性");
        } else if (response.getMaxSimilarity() < 30) {
            suggestions.add("题目存在一定重复，建议调整");
            suggestions.add("考虑增加更具体的应用场景描述");
            suggestions.add("可以加入研究方法的限定词");
        } else {
            suggestions.add("题目重复率较高，建议重新选题");
            suggestions.add("考虑更换研究方向或角度");
            suggestions.add("建议与导师讨论确定新题目");
        }

        suggestions.add("确保题目能够准确反映研究内容");
        suggestions.add("避免使用过于宽泛的表述");

        return suggestions;
    }

    private void saveDuplicateResults(Long taskId, List<TitleCheckResponse.DuplicateResult> results) {
        if (results == null || results.isEmpty()) return;

        log.info("开始保存 {} 个相似结果到数据库", results.size());

        for (TitleCheckResponse.DuplicateResult result : results) {
            TitleDuplicateResult duplicate = new TitleDuplicateResult();
            duplicate.setCheckTaskId(taskId);
            duplicate.setSimilarTitle(result.getTitle());
            duplicate.setSimilarity(result.getSimilarity());
            duplicate.setAuthor(result.getAuthor());
            duplicate.setClassName(result.getClassName());
            duplicate.setYear(result.getYear());
            duplicate.setPaperId(result.getPaperId());

            duplicateResultMapper.insert(duplicate);
        }

        log.info("相似结果保存完成");
    }

    /**
     * 获取查重历史 - 使用PageHelper分页
     */
    public PageInfo<TitleCheckHistoryResponse> getCheckHistory(Long studentId, int page, int size) {
        log.info("获取查重历史 - 学生ID: {}, 页码: {}, 大小: {}", studentId, page, size);

        try {
            // 使用PageHelper分页
            PageHelper.startPage(page, size);

            List<TitleCheckTask> tasks = titleCheckTaskMapper.findByStudentId(studentId);
            log.info("查询到 {} 条历史记录", tasks.size());

            List<TitleCheckHistoryResponse> historyList = tasks.stream().map(task -> {
                TitleCheckHistoryResponse history = new TitleCheckHistoryResponse();
                history.setId(task.getId());
                history.setTitle(task.getTitle());

                // 处理可能的空值
                history.setMaxSimilarity(task.getMaxSimilarity() != null ? task.getMaxSimilarity() : 0.0);
                history.setDuplicateCount(task.getDuplicateCount() != null ? task.getDuplicateCount() : 0);
                history.setRiskLevel(task.getRiskLevel() != null ? task.getRiskLevel() : "low");
                history.setCheckTime(task.getCheckTime());

                return history;
            }).collect(Collectors.toList());

            PageInfo<TitleCheckHistoryResponse> pageInfo = new PageInfo<>(historyList);
            log.info("分页信息 - 总数: {}, 页数: {}, 当前页记录数: {}",
                    pageInfo.getTotal(), pageInfo.getPages(), pageInfo.getList().size());

            return pageInfo;

        } catch (Exception e) {
            log.error("获取查重历史失败", e);
            // 返回空的分页结果
            return new PageInfo<>(Collections.emptyList());
        }
    }

    /**
     * 备用的手动分页方法（如果PageHelper有问题）
     */
    public PageInfo<TitleCheckHistoryResponse> getCheckHistoryManual(Long studentId, int page, int size) {
        log.info("使用手动分页获取查重历史 - 学生ID: {}, 页码: {}, 大小: {}", studentId, page, size);

        try {
            int offset = (page - 1) * size;

            // 获取总数
            Long total = titleCheckTaskMapper.countByStudentId(studentId);

            // 获取分页数据
            List<TitleCheckTask> tasks = titleCheckTaskMapper.findByStudentIdWithPage(studentId, offset, size);
            log.info("手动分页查询到 {} 条历史记录", tasks.size());

            List<TitleCheckHistoryResponse> historyList = tasks.stream().map(task -> {
                TitleCheckHistoryResponse history = new TitleCheckHistoryResponse();
                history.setId(task.getId());
                history.setTitle(task.getTitle());
                history.setMaxSimilarity(task.getMaxSimilarity() != null ? task.getMaxSimilarity() : 0.0);
                history.setDuplicateCount(task.getDuplicateCount() != null ? task.getDuplicateCount() : 0);
                history.setRiskLevel(task.getRiskLevel() != null ? task.getRiskLevel() : "low");
                history.setCheckTime(task.getCheckTime());
                return history;
            }).collect(Collectors.toList());

            // 手动创建PageInfo
            PageInfo<TitleCheckHistoryResponse> pageInfo = new PageInfo<>(historyList);
            pageInfo.setPageNum(page);
            pageInfo.setPageSize(size);
            pageInfo.setTotal(total);
            pageInfo.setPages((int) Math.ceil((double) total / size));

            log.info("手动分页完成 - 总数: {}, 总页数: {}", total, pageInfo.getPages());

            return pageInfo;

        } catch (Exception e) {
            log.error("手动分页获取查重历史失败", e);
            return new PageInfo<>(Collections.emptyList());
        }
    }

    public TitleCheckResponse getCheckResult(Long taskId, Long studentId) {
        log.info("获取查重结果详情 - 任务ID: {}, 学生ID: {}", taskId, studentId);

        TitleCheckTask task = titleCheckTaskMapper.findById(taskId);
        if (task == null) {
            throw new RuntimeException("查重任务不存在");
        }

        if (!task.getStudentId().equals(studentId)) {
            throw new RuntimeException("无权访问该查重结果");
        }

        List<TitleDuplicateResult> duplicates = duplicateResultMapper.findByCheckTaskId(taskId);
        log.info("查询到 {} 个相似结果", duplicates.size());

        List<TitleCheckResponse.DuplicateResult> duplicateResults = duplicates.stream()
                .map(dup -> {
                    TitleCheckResponse.DuplicateResult result = new TitleCheckResponse.DuplicateResult();
                    result.setTitle(dup.getSimilarTitle());
                    result.setSimilarity(dup.getSimilarity());
                    result.setAuthor(dup.getAuthor());
                    result.setClassName(dup.getClassName());
                    result.setYear(dup.getYear());
                    result.setPaperId(dup.getPaperId());
                    return result;
                })
                .collect(Collectors.toList());

        List<String> suggestions = Collections.emptyList();
        if (task.getSuggestions() != null) {
            try {
                suggestions = objectMapper.readValue(task.getSuggestions(),
                        new TypeReference<List<String>>() {});
            } catch (Exception e) {
                log.warn("解析建议失败", e);
            }
        }

        TitleCheckResponse response = new TitleCheckResponse();
        response.setId(task.getId());
        response.setTitle(task.getTitle());
        response.setMaxSimilarity(task.getMaxSimilarity() != null ? task.getMaxSimilarity() : 0.0);
        response.setAvgSimilarity(task.getAvgSimilarity() != null ? task.getAvgSimilarity() : 0.0);
        response.setDuplicateCount(task.getDuplicateCount() != null ? task.getDuplicateCount() : 0);
        response.setRiskLevel(task.getRiskLevel() != null ? task.getRiskLevel() : "low");
        response.setCheckScope(task.getCheckScope());
        response.setYearRange(task.getYearRange());
        response.setCheckTime(task.getCheckTime());
        response.setDuplicateResults(duplicateResults);
        response.setSuggestions(suggestions);

        return response;
    }



    /**
     * 获取题目查重统计（真实数据）
     */
    public DashboardStatsResponse getTitleCheckStats(Long studentId) {
        try {
            log.info("获取题目查重统计 - 学生ID: {}", studentId);

            TitleCheckStats stats = titleCheckTaskMapper.findStatsByStudentId(studentId);
            DashboardStatsResponse response = new DashboardStatsResponse();

            if (stats != null) {
                response.setTitleCheckCount(stats.getTotalCount() != null ? stats.getTotalCount() : 0L);

                // 设置最近查重时间
                if (stats.getLastCheckTime() != null) {
                    response.setLastCheckTime(stats.getLastCheckTime());
                    // 计算最近查重天数
                    long daysBetween = ChronoUnit.DAYS.between(stats.getLastCheckTime(), LocalDateTime.now());
                    response.setLastCheckDays(Math.max(0, (int) daysBetween));
                } else {
                    response.setLastCheckTime(null);
                    response.setLastCheckDays(0);
                }
            } else {
                response.setTitleCheckCount(0L);
                response.setLastCheckTime(null);
                response.setLastCheckDays(0);
            }

            log.info("题目查重统计结果: {}", response);
            return response;

        } catch (Exception e) {
            log.error("获取题目查重统计失败", e);
            DashboardStatsResponse response = new DashboardStatsResponse();
            response.setTitleCheckCount(0L);
            response.setLastCheckTime(null);
            response.setLastCheckDays(0);
            return response;
        }
    }

    /**
     * 获取最近查重记录（真实数据）
     */
    public List<RecentRecordResponse> getRecentRecords(Long studentId, int limit) {
        try {
            log.info("获取最近查重记录 - 学生ID: {}, 限制: {}", studentId, limit);

            List<RecentRecordResponse> records = new ArrayList<>();

            // 获取最近题目查重记录（真实数据）
            List<TitleCheckTask> titleTasks = titleCheckTaskMapper.findRecentByStudentId(studentId, limit);
            for (TitleCheckTask task : titleTasks) {
                RecentRecordResponse record = new RecentRecordResponse();
                record.setId(task.getId());
                record.setType("title");
                record.setTitle(task.getTitle());
                record.setSimilarity(task.getMaxSimilarity() != null ? task.getMaxSimilarity() : 0.0);
                record.setTime(task.getCheckTime());
                records.add(record);
            }

            // 获取最近信息提取记录（真实数据）
            List<PaperExtractionTask> extractionTasks = paperExtractionTaskMapper.findRecentByStudentId(studentId, limit);
            for (PaperExtractionTask task : extractionTasks) {
                RecentRecordResponse record = new RecentRecordResponse();
                record.setId(task.getId());
                record.setType("extraction");
                record.setTitle(task.getFileName() != null ? task.getFileName() : "论文信息提取");
                record.setSimilarity(0.0); // 信息提取没有相似度
                record.setTime(task.getCreateTime());
                records.add(record);
            }

            // 按时间排序并限制数量
            records.sort((a, b) -> b.getTime().compareTo(a.getTime()));
            if (records.size() > limit) {
                records = records.subList(0, limit);
            }

            log.info("获取到 {} 条最近记录", records.size());
            return records;

        } catch (Exception e) {
            log.error("获取最近查重记录失败", e);
            return new ArrayList<>();
        }
    }


}